import logging
import threading
import time
import traceback

from PySide6.QtCore import Signal, QObject
from PySide6.QtGui import Qt

# 设置日志记录的基本配置
logging.basicConfig(level=logging.ERROR, format='%(asctime)s - %(levelname)s - %(message)s')
日志记录器 = logging.getLogger(__name__)

# 使用 PySide6 实现动态数据调度器的属性管理器基类
class 属性管理基类(QObject):
    属性变化信号 = Signal(str, object)  # 全局信号，用于通知所有属性的变化
    """
    当前设计下 属性管理器信号传播时手动的 如非手动触发，则不会触发属性的的跨越性同步。
       如需跨越性同步，则需要在回调函数中手动触发属性的同步。
    """
    def __init__(self):
        super().__init__()
        self.调试模式 = False  # 调试模式开关
        if self.调试模式:
            日志记录器.setLevel(logging.DEBUG)
            # 连接全局信号
            self.属性变化信号.connect(self.全局信号触发监控)
        else:
            日志记录器.setLevel(logging.ERROR)
        # 线程属性通讯


        # 管理器 = Manager()
        # 共享字典 = 管理器.dict()
        self._属性 = {}
        self._同步回调绑定 = {}  # 同步回调函数绑定
        self._线程池回调绑定 = {}  # 线程池回调函数绑定
        self.属性变化信号触发次数 = 0
        self._属性同步对象=None
        self._属性修改锁 = threading.RLock()
    @property
    def 属性同步对象(self):
        if self._属性同步对象 is None:
            raise ValueError("同步对象未设置")
        return self._属性同步对象

    @属性同步对象.setter
    def 属性同步对象(self, 对象实例):
        # 同步对象必须是某个类的实例  并且  该类的基类是属性管理基类
        if  not issubclass(对象实例.__class__, 属性管理基类):
            raise ValueError("同步对象必须的基类必须是是属性管理基类")
        self._属性同步对象 = 对象实例
        self._同步属性()
        self._属性同步对象.属性变化信号.connect(self.设置属性触发函数, Qt.QueuedConnection)
        self.属性变化信号.connect(self.属性同步对象.设置属性触发函数, Qt.QueuedConnection)
    def _同步属性(self):
        日志记录器.debug("同步属性")
        # for 属性名, 属性值 in self._属性.items():
        #     日志记录器.debug(f"同步属性: {属性名} -> {属性值}")
        #     self.属性同步对象._设置自身属性(属性名, 属性值)
        for 属性名, 属性值 in self.属性同步对象._属性.items():
            日志记录器.debug(f"同步属性: {属性名} -> {属性值}")
            self._设置自身属性(属性名, 属性值)
    def 全局信号触发监控(self, 属性名, 属性值):
        self.属性变化信号触发次数 += 1
        日志记录器.debug(f"全局信号触发监控: 属性名：{属性名}, 属性当前值: {属性值}, 触发次数: {self.属性变化信号触发次数}")

    def 注册属性触发函数(self, 属性名, 回调函数):
        """注册同步回调函数"""
        if not callable(回调函数):
            raise ValueError("回调函数必须是可调用的")
        if self._同步回调绑定.get(属性名) is None:
            self._同步回调绑定[属性名]=set()
        self._同步回调绑定[属性名].add(回调函数)
        日志记录器.debug(f"注册同步回调函数: {属性名} -> {回调函数}")
    def 注销属性所有触发函数(self, 属性名):
        """注销同步回调函数"""
        if 属性名 in self._同步回调绑定:
            self._同步回调绑定[属性名]=None
            日志记录器.debug(f"注销同步回调函数: {属性名}")
    def 注销属性触发函数(self,属性名,回调函数):
        """注销同步回调函数"""
        if 属性名 in self._同步回调绑定 and 回调函数 in self._同步回调绑定[属性名]:
            self._同步回调绑定[属性名].remove(回调函数)
            日志记录器.debug(f"注销同步回调函数: {属性名} -> {回调函数}")
    def 设置属性触发函数(self, 属性名, 属性值):
        """触发回调函数的三种方式"""
        if not isinstance(属性名, str):
            raise ValueError("属性名必须是字符串")
        if self._设置自身属性(属性名, 属性值):
            # 同步回调
            if 属性名 in self._同步回调绑定:
                try:
                    for 回调函数 in self._同步回调绑定.get(属性名):
                        回调函数(属性值)
                    日志记录器.debug(f"设置属性触发属性更新函数: 属性名:{属性名}, 属性值: {属性值}")
                except Exception as e:
                    日志记录器.error(f"同步回调函数调用失败: {e}")
                    traceback.print_exc()
            return True
        return False

    def 设置属性触发信号(self, 属性名, 属性值):
        """触发全局信号，通知所有属性的变化"""
        if not isinstance(属性名, str):
            raise ValueError("属性名必须是字符串")
        if self._设置自身属性(属性名, 属性值):
            self.属性变化信号.emit(属性名, 属性值)  # 触发全局信号
            日志记录器.debug(f"设置属性触发属性变化信号: 属性名:{属性名}, 属性值: {属性值}")
            return True
        return False

    def _设置自身属性(self, 属性名, 属性值):
        """线程安全的属性设置"""
        if not isinstance(属性名, str):
            raise ValueError("属性名必须是字符串")
        with self._属性修改锁:
            if self._属性.get(属性名) !=  属性值:
                日志记录器.info(f"设置自身属性: 属性名:{属性名}, 属性值: {属性值}")
                self._属性[属性名] = 属性值
                return True
            else:
                日志记录器.debug(f"属性值未变动: 属性名:{属性名}, 属性值: {属性值}")
                return False

    def 获取属性值(self, 属性名):
        """线程安全的属性获取"""
        with self._属性修改锁:
            if not isinstance(属性名, str):
                raise ValueError("属性名必须是字符串")
            return self._属性.get(属性名)

    @property
    def 属性(self):
        """线程安全的属性获取"""
        with self._属性修改锁:
            return self._属性

    def 设置属性(self, 属性名, 属性值):
        """设置属性，触发属性变化信号和回调函数"""
        self.设置属性触发信号(属性名, 属性值)
        #起始接口.设置属性触发属性更新函数(属性名, 属性值)


# import unittest
# from PySide6.QtCore import QCoreApplication
# from PySide6.QtTest import QTest
#
# class 测试属性管理(unittest.TestCase):
#     def setUp(self):
#         """测试准备"""
#         self.应用程序 = QCoreApplication([])  # 初始化Qt应用
#         self.应用程序.processEvents()  # 处理事件
#         self.管理器1 = 属性管理基类()  # 创建属性管理实例1
#         self.管理器2 = 属性管理基类()  # 创建属性管理实例2
#         self.变更计数 = 0  # 属性变更计数
#
#         # 注册属性变更回调函数
#         self.管理器2.注册属性变动触发函数('测试属性', self.属性变更回调)
#
#         # 设置同步对象
#         self.管理器1.属性同步对象 = self.管理器2
#
#     def 属性变更回调(self, 新值):
#         """属性变更时的回调函数"""
#         self.变更计数 += 1  # 每次属性变更时计数+1
#         日志记录器.debug(f"属性变更回调被调用，新的值: {新值}")  # 添加调试信息
#         # 在此处我们同时修改属性，测试信号风暴的情况
#         self.管理器2.设置属性('测试属性', 新值 + 1)
#
#     def test属性同步(self):
#         """测试属性同步效果"""
#         self.管理器1.设置属性('测试属性', 10)  # 设置管理器1的属性
#         # 等待属性同步完成
#         QTest.qWait(100)  # 等待信号被处理
#
#         # 验证属性是否同步
#         self.assertEqual(self.管理器2.获取属性('测试属性'), 10, "属性未成功同步到管理器2")
#         self.assertLessEqual(self.变更计数, 1, "信号风暴发生：回调函数应未被多次调用。")
#         # 添加更多的日志信息以调试
#         日志记录器.debug(f"管理器2当前属性: {self.管理器2.属性}")  # 输出当前管理器2的所有属性
#
#     def tearDown(self):
#         """清理工作"""
#         del self.管理器1  # 删除管理器1
#         del self.管理器2  # 删除管理器2
#         del self.应用程序  # 删除Qt应用实例
#
#
# if __name__ == '__main__':
#     unittest.main()  # 运行单元测试
